import axios from 'axios'
import { ElMessage } from 'element-plus'
import store from '@/store'
import router from '@/router'
import { bus } from '@/utils/common'
// http://www.ali.com/api/v1/good/list  => /good/list
// http://www.ali.com/api/v1/good/1
// http://www.ali.com/api/v1/banner/list

const request = axios.create({
  // 最长请求时长
  timeout: 10000,
  // baseURL 配置基础路径
  // 可以根据当前的环境(开发环境/生产环境)来配置不同的路径
  baseURL: import.meta.DEV ? 'http://121.89.205.189:3000/admin' : 'http://121.89.205.189:3000/admin'
})

// 请求拦截器, 会在真正的发出请求前, 接收到config
// config其实就是此次请求的配置对象, 上面存有此次请求所有的信息
// 可以对config对象一些配置处理, 添加参数, 参数转化... 必须将 config 返回回去
request.interceptors.request.use((config) => {
  // 传递token
  config.headers.token = store.state.authority.token
  // 全局loading
  bus.emit('global:loading.update', true)
  return config
}, (error) => {
  ElMessage({ type: 'error', message: '请求失败, 请再次尝试' })
  // 全局loading
  bus.emit('global:loading.update', false)
  throw error
})





// 响应拦截器, 服务器做出响应, axios还没有返回的时候执行
// 需要返回, 返回的内容就是请求结果拿到的内容
request.interceptors.response.use((res) => {
  // config 此次请求相关的配置, 可以做一些判断
  // data 服务响应的内容, 在这个项目中 服务端响应了 code/data/message
  // headers 响应头 可以做一些判断
  // request 请求工具
  // status 和 statusText 此次请求的状态
  const isSuccess = res.data.code === '200'
  const isTokenBroken = res.data.code === '10119'
  const { method, silent, loud, more } = res.config
  // UI反馈
  if (method !== 'get' || !isSuccess) {
    if (!silent) {
      if (isTokenBroken) {
        ElMessage({ type: 'error', message: '登录过期, 请重新登录' })
        // 删除掉用户信息
        store.dispatch('authority/deleteStateInStorageAction')
        // 返回到登录页面
        router.push({ name: 'login' })
      }
      else ElMessage({ type: isSuccess ? 'success' : 'error', message: res.data.message })
    }
  }
  if (loud) ElMessage({ type: isSuccess ? 'success' : 'error', message: res.data.message })
    
  bus.emit('global:loading.update', false)

  // 当前项目中, 只要res.data.code !== 200, 说明请求结果失败了, 应该统一做UI反馈
  // 还有就是, 有点时候我们需要在逻辑中对此次请求的成功和失败(code === 200)再做出单独的处理
  // 逻辑就要有能判断成功和失败的能力
  // 如果我们在拦截的返回值上做文章的话,很可能出现混淆的情况, 比如: 成功就返回res.data.data, 失败就不返回或者返回false
  // 此时,我们无法保证会不会出现 某个结果成功的返回值就是false或者没有返回值

  // 所以这里,可以在失败的时候抛出错误, 就可以做到准确区分, 并且在逻辑中可以利用try catch来 "分流"
  // RESTFUL API
  // http://www.ss.cn/api/v3/banner/delete
  // { code, msg, data }

  if (isSuccess) {
    // 成功, 直接返回真正的数据
    
    return more ? res.data : res.data.data
  }
  // 失败
  throw new Error(res.data.code)
}, (error) => {
  // 请求过程失败
  ElMessage({ type: 'error', message: '网络请求失败' })
  bus.emit('global:loading.update', false)
  throw error
})

export default request
